1. Field of the Invention
The present invention relates generally to information processing environments and, more particularly, to a system and methodology for design-time dynamic class type construction.
2. Description of the Background Art
Before a digital computer may accomplish a desired task, it must receive an appropriate set of instructions. Executed by the computer's microprocessor, these instructions, collectively referred to as a “computer program”, direct the operation of the computer. Expectedly, the computer must understand the instructions which it receives before it may undertake the specified activity.
Owing to their digital nature, computers essentially only understand “machine code”, i.e., the low-level, minute instructions for performing specific tasks—the sequence of ones and zeros that are interpreted as specific instructions by the computer's microprocessor. Since machine language or machine code is the only language computers actually understand, all other programming languages represent ways of structuring human language so that humans can get computers to perform specific tasks.
While it is possible for humans to compose meaningful programs in machine code, practically all software development today employs one or more of the available programming languages. The most widely used programming languages are the “high-level” languages, such as C++, Pascal, Java®, and C#®. These languages allow data structures and algorithms to be expressed in a style of writing that is easily read and understood by fellow programmers.
A language “compiler” is a program that takes human authored source code logic and transforms that into mechanical binary logic (machine code instructions) for a given target program. In a typical implementation, a compiler includes operational stages of scanning/parsing the source code, tokenizing the source code, and recognizing symbols and language logic, for purposes of converting the source code into an internal representation. A modern day compiler will iterate over the internal representation to optimize the selection of machine code instructions. Ultimately, the compiler emits a sequence of machine code instructions which comprise the binary logic for the compiled source code. The ultimate output of the compiler is a compiled module such as a compiled C++ “object module”, which includes instructions for execution ultimately by a target processor, or a compiled Java class, which includes bytecodes for execution ultimately by a Java virtual machine.
Although an object module includes code for instructing the operation of a computer, the object module itself is not usually in a form which may be directly executed by a computer. This binary logic is typically linked with other compiled modules to produce the ultimate executable program. Linking may be thought of as the general process of combining or linking together one or more compiled object modules or units to create an executable program. This task usually falls to a program called a “linker.” After resolving interconnecting references as needed, the linker constructs an executable image by organizing the object code from the modules of the program in a format understood by the operating system program loader. The end result of linking is executable code (typically an .EXE file) which, after testing and quality assurance, is passed to the user with appropriate installation and usage instructions.
Integrated development environments, such as Borland® Delphi™, Borland® JBuilder®, and Borland® C# Builder® (all available from assignee Borland Software Corporation of Scotts Valley, Calif.), are the preferred application development environments for quickly creating production applications. Such environments are characterized by an integrated development environment (IDE) providing a form designer, a property getter/setter manager (“inspector”), a project manager, a tool palette (with objects which the user can drag and drop on forms), an editor, a debugger, and a compiler. In general operation, the user “paints” objects on one or more forms, using the form designer. Attributes and properties of the objects on the forms can be modified using the property manager or inspector. In conjunction with this operation, the user attaches or associates program code with particular objects on the screen (e.g., button object). Typically, code is generated by the IDE in response to user actions in the form designer and the user then manipulates the generated code using the editor. Changes made by the user to code in the editor are reflected in the form designer, and vice versa. After the program code has been developed, the compiler is used to generate object code for execution on a machine.
Today, most software development occurs within the context of a development framework. Microsoft's .NET framework is a new framework that has gained a lot of attention lately. The .NET framework is a collection of classes implemented on top of a Common Language Runtime (“CLR”) system providing containers, strings, components, interfaces, streams, and user interface control classes for use by programmers writing applications to run in the .NET execution environment (the .NET platform). The CLR is a program execution architecture which includes rich type information at runtime, an intermediate abstract machine instruction set that is compiled to native machine instructions at runtime, and a variety of system services to automate remote procedure calls over network connections, security checks, and garbage-collected memory management. The core infrastructure of CLR is defined in documents published by the ECMA standards body (Ecma International, a European association for standardizing information and communication systems). Technically, the .NET architecture can be implemented independently of Microsoft, such as illustrated by the Mono project by Novell, Inc. of Waltham, Mass.
With adoption of new development frameworks, such as Microsoft's .NET framework, a problem arises with efficiently migrating existing programs and tools to these new development frameworks. For example, the form designer used in the Borland® Delphi™ IDE running on Microsoft Windows 32-bit operating systems (hereinafter “Win-32”) relies on being able to dynamically construct a new form class “on-the-fly”. To dynamically construct a new form class, additional metadata is added to a class that describes its layout and structure based on what the compiler saw at compile-time. Things like the class name of the new form class as well as method names, method addresses, field names and field addresses, and the like are encoded into tables that are accessible at run-time. These tables are used by the property-based streaming system to allow persisting of any type of class. By generating these tables “on-the-fly”, the layout and structure of a “new” form class can be simulated as it is being constructed by the form designer. The property-based streaming system does not know the difference between the newly built class and a compiler-built class. Thus, when an instance of this new class is constructed it appears, for all intents and purposes, to be an instance of the new class type.
A problem arises however in attempting to use this same approach in conjunction with new development frameworks, such as the Microsoft .NET framework. In order to use Microsoft's .NET framework and the Common Language Runtime (hereinafter, the “.NET framework”), one must follow certain rules set forth by the .NET framework. In this environment it is not feasible to dynamically construct a new class on-the-fly by generating the class metadata as a function of in-memory tables of a certain structure. This approach is not permitted in a managed code environment such as that provided by the .NET framework.
From a user standpoint, however, the user that is developing an application for a new framework (e.g., the .NET framework) wants to be able to use the existing development tools and interfaces in the same manner as in the past. Although other form-based designers are available (e.g., Microsoft WinForm designer), it does not provide the same features or functionality and would require developers already familiar another designer (e.g., the Delphi form designer) to learn a new tool. The ability to use existing tools with which a developer/user is familiar makes it easier to transition to a new framework. However, to provide the familiar development tools and interfaces (e.g., an IDE form designer) on the new framework requires modifications to the underlying infrastructure supporting the operation of these development tools because of the constraints imposed by the new framework (e.g., the .NET framework).
For example, the .NET framework imposes certain constraints which preclude directly accessing raw metadata information, including the metadata which describes the different classes and types in the system. In contrast, in the native Win-32 machine code generated environment, metadata information could be directly generated and manipulated (e.g., in the dynamic creation of forms by an IDE). For instance, in the Win-32 environment, the dynamic generation of forms by the Delphi form designer is implemented based on the ability to control the raw metadata information and perform direct manipulation of that information. Creating and regenerating forms in the form designer in this environment relies on this ability to directly manipulate metadata information. The Microsoft .NET framework environment, however, does not allow this type of direct metadata manipulation as it violates the tenets that the managed execution environment supports. Accordingly, in order to provide users (e.g., application developers) with the same development experience of the familiar form designer of existing development systems (e.g., the Delphi development system), the underlying infrastructure of the development system must be modified in order to provide this functionality in the managed execution environment provided by the .NET framework.
What is needed is a solution that enables a new class type to be dynamically constructed “on-the-fly” at design time on a development framework, such as the .NET framework. The solution should, for instance, be able to persist the state of a form that is being visually designed in a development system without direct generation and manipulating of underlying metadata information. Also, the solution should be implemented in a manner that does not require the existing development environment in which the form designer is implemented to be completely rearchitected. Ideally, the ability to support dynamic generation of forms should be implemented in an isolated way that does not require wholescale modification of the entire development environment. The present invention provides a solution to these and other needs.